package jm.nj.demo15mian.demo03;

import jm.nj.demo15mian.demo02.Person;

import java.lang.reflect.Constructor;

/*
 * 通过反射技术
 * 获取class文件对象
 * 通过Class对象中提供的方法获取类中的构造方法
 * 执行获取到的构造方法
 *   public Person()
 *   public Person(String id ,String name,int age)
 *   private Person(String name, int age)
 * */
public class Demo02Reflect {
    public static void main(String[] args) throws Exception {
        //获取class文件对象
        Class clazz = Class.forName("jm.nj.demo15mian.demo02.Person");

        //通过Class对象中提供的方法获取类中的构造方法
        /*
         * Constructor<?>[] getConstrutors()  获取类中的公共(public)构造方法
         * Constructor<?>[] getDeclaredConstrutors()  获取类中的公共(public)构造方法
         *
         * */
        Constructor[] cons = clazz.getConstructors();
        for (Constructor con : cons) {
            System.out.println(con);
        }
        System.out.println("==============");

        /*
         * Constructor<T> getConstructor(Class<?>... parameterTypes) 获取指定的公共的构造方法
         * Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)  获取指定的的构造方法,包含私有的
         * ...:可变参数,可以有,可有没有,可以有多个
         * parameterTypes:构造方法参数的class对象
         * 	String.class
         * 	int.class
         */
        //public Person()
        Constructor con1 = clazz.getConstructor();
        System.out.println(con1);
        //public Person(String id, String name, int age)
        Constructor con2 = clazz.getConstructor(String.class, String.class, int.class);
        System.out.println(con2);

        //private Person(string name, int age)
        Constructor con3 = clazz.getDeclaredConstructor(String.class, int.class);
        System.out.println(con3);

        /*
         * 执行获取到的构造方法
         *
         * Constructor类中 的方法
         * T  newInstance(Object...intargs)
         *       使用此Constructor对象表示的构造方法来创建该构造方法的声明类的新实例,
         *                   并用指定的初始化参数初始化该实例
         *       参数initargs:调用构造方法时传递的实际参数
         *       等同于==>new Person("001","张三",18);
         * */

        /*Person p1 = new Person();
        System.out.println(p1);*/

        Object obj1 = con1.newInstance();
        System.out.println(obj1);

        //向下转型
       /* Person p1 = (Person)obj1;
        p1.setAge(19);
        System.out.println(p1);*/

        /*Person p2 = new Person("001","张三",18);
        System.out.println(p2);*/
        Object obj2 = con2.newInstance("001", "张三", 18);
        System.out.println(obj2);

        //Person p3 = new Person("张三",18);
        /*
        * 私有的构造方法,不能执行,有权限检查:抛出IllegalAccessException
        * Constructor父类AccessibleObject中有一个方法
        * void setAccessible(boolean flag)
        将此对象的 accessible 标志设置为指示的布尔值。
		 * 	值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。
		 * 	值为 false 则指示反射的对象应该实施 Java 语言访问检查
        * */

        con3.setAccessible(true);//取消Java访问权限检查==>暴力反射
        Object obj3 = con3.newInstance("张三",18);
        System.out.println(obj3);
    }
}
